/**
 * 
 */
package dms.repository.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;

import dms.model.Building;
import dms.model.Dormitory;
import dms.model.form.PurchaseItem;
import dms.model.util.FindUtil;
import dms.model.util.PageIterator;
import dms.repository.PurchaseItemRepository;
import dms.util.HibernateUtil;

/**
 * @author 李健
 *
 */
public class PurchaseItemRepositoryHibernate implements PurchaseItemRepository {

	private static final Log log = LogFactory.getLog(DormitoryRepositoryHibernate.class);

	
	/* (non-Javadoc)
	 * @see dms.repository.PurchaseItemRepository#createPurchaseItem(dms.model.form.PurchaseItem)
	 */
	@Override
	public PurchaseItem createPurchaseItem(PurchaseItem purchaseItemInfo) throws Exception {
		Session session = null;
		Transaction tx = null;
		
		try {
			session = HibernateUtil.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			session.save(purchaseItemInfo);

			tx.commit();
		} catch (Exception e) {
			log.error(e.getMessage());
			if (tx != null) {
				tx.rollback();
			}
			throw e;
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		
		return purchaseItemInfo;
	}

	/* (non-Javadoc)
	 * @see dms.repository.PurchaseItemRepository#deletePurchaseItemById(java.lang.Long)
	 */
	@Override
	public void deletePurchaseItemById(Long id) throws Exception {
		Session session = null;
		Transaction tx = null;
		
		try {
			session = HibernateUtil.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			PurchaseItem pi = (PurchaseItem) session.load(PurchaseItem.class, id);
			session.delete(pi);

			tx.commit();
		} catch (Exception e) {
			log.error(e.getMessage());
			if (tx != null) {
				tx.rollback();
			}
			throw e;
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}

	}

	/* (non-Javadoc)
	 * @see dms.repository.PurchaseItemRepository#findByBuilding(int, int, dms.model.Building, java.util.Date, java.util.Date)
	 */
	@Override
	public PageIterator<PurchaseItem> findByBuilding(int start, int count,
			Building building, Date fromDate, Date toDate, Boolean processed, Boolean applied) {
		Map keyValue = new HashMap();
		keyValue.put("dormitory.building", building);
		return find(start, count, keyValue, fromDate, toDate, processed, applied);
	}

	/* (non-Javadoc)
	 * @see dms.repository.PurchaseItemRepository#findByDormitory(int, int, dms.model.Dormitory, java.util.Date, java.util.Date)
	 */
	@Override
	public PageIterator<PurchaseItem> findByDormitory(int start, int count,
			Dormitory dormitory, Date fromDate, Date toDate, Boolean processed, Boolean applied) {
		Map keyValue = new HashMap();
		keyValue.put("dormitory", dormitory);
		return find(start, count, keyValue, fromDate, toDate, processed, applied);
	}

	/* (non-Javadoc)
	 * @see dms.repository.PurchaseItemRepository#findById(java.lang.Long)
	 */
	@Override
	public PurchaseItem findById(Long id) {
		Session session = null;
		Transaction tx = null;
		
		PurchaseItem pi = null;
		try {
			session = HibernateUtil.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			pi = (PurchaseItem) session.load(PurchaseItem.class, id);
			//initialize property
			Hibernate.initialize(pi);
			
			
			tx.commit();
		} catch (Exception e) {
			log.error(e.getMessage());
			if (tx != null) {
				tx.rollback();
			}
			
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		return pi;
	}


	
	private PageIterator<PurchaseItem> find(int start, int count, Map keyValue, Date fromDate, Date toDate, Boolean processed, Boolean applied) {
		Session session = null;
		Transaction tx = null;
		List<PurchaseItem> list = null;
		PageIterator<PurchaseItem> iter = null;
		Long allCount = null;		
		
		String countQuery = "select count(*) from PurchaseItem p  ";
		String findQuery = "select p from PurchaseItem p  ";
		StringBuilder conditionQuery = new StringBuilder("");
		Collection params = new ArrayList();
		
		if (conditionQuery.indexOf("where") == -1) {
			conditionQuery.append(" where ");
		}
		
		if (keyValue != null) {
			
			Set set = keyValue.entrySet();
			Iterator keyIter = set.iterator();
			while (keyIter.hasNext()) {
				Map.Entry<String, Object> entry = (Entry<String, Object>) keyIter
						.next();
				String name = entry.getKey();
				Object value = entry.getValue();

				conditionQuery.append(" p." + name + " = ? and ");
				params.add(value);
			}
		}
		/*if (conditionQuery.indexOf("where") == -1) {
			conditionQuery.append(" where ");
		}*/
		if (fromDate != null && toDate == null) {
			conditionQuery.append("  p.requestDate >= ?  and ");
			params.add(fromDate);
		}
		if (fromDate == null && toDate != null) {
			conditionQuery.append("  p.requestDate <= ?  and ");
			params.add(toDate);
		}
		if (fromDate != null && toDate != null) {
			conditionQuery.append("  (p.requestDate between ? and ?)  and ");
			params.add(fromDate);
			params.add(toDate);
		}

		if (processed != null && applied != null) {
			if (processed == true && applied == false) {
				conditionQuery.append(" p.status.processed = true and p.status.applied = false and ");
			}
			if (applied == true && processed == true) {
				conditionQuery.append(" p.status.applied = true and p.status.processed = true and ");
			}
		}
		if (processed == null && applied != null) {
			if (applied == true) {
				conditionQuery.append(" p.status.applied = true and p.status.processed = true and ");
			} else {
				conditionQuery.append(" p.status.processed = true and p.status.applied = false and ");
			}
		}
		
		if (processed != null && applied == null) {
			if (processed == true) {
				conditionQuery.append(" p.status.applied = false and p.status.processed = true and ");
			} 
		}
		conditionQuery.append(" p.id = p.id ");
		countQuery += conditionQuery;
		findQuery += conditionQuery;
		
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			
			allCount = FindUtil.calculateAllCount(session, countQuery, params);
			list = FindUtil.getEntitiesByPage(session, findQuery, params, start, count);
			iter = new PageIterator<PurchaseItem>(list, allCount, start, count);
			
			tx.commit();
		} catch (Exception e) {
			log.error(e.toString());
			if (tx != null) {
				tx.rollback();
			}
			
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
				
			}
		}
		return iter;
	}
	
	/* (non-Javadoc)
	 * @see dms.repository.PurchaseItemRepository#updatePurchaseItem(dms.model.form.PurchaseItem)
	 */
	@Override
	public PurchaseItem updatePurchaseItem(PurchaseItem purchaseItemInfo) throws Exception {
		Session session = null;
		Transaction tx = null;
		PurchaseItem pi = null;
		
		try {
			session = HibernateUtil.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			pi = (PurchaseItem) session.merge(purchaseItemInfo);

			tx.commit();
		} catch (Exception e) {
			log.error(e.getMessage());
			if (tx != null) {
				tx.rollback();
			}
			throw e;
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		return pi;
	}

	@Override
	public void deletePurchaseItems(List<Long> ids) throws Exception {
		Session session = null;
		Transaction tx = null;
		String deleteQuery = " delete from PurchaseItem p where p.id in (:ids) ";
		try {
			session = HibernateUtil.getSessionFactory().getCurrentSession();
			tx = session.beginTransaction();
			
			session.createQuery(deleteQuery)
				   .setParameterList("ids", ids)
				   .executeUpdate();

			tx.commit();
		} catch (Exception e) {
			log.error(e.getMessage());
			if (tx != null) {
				tx.rollback();
			}
			throw e;
		} finally {
			if (session != null) {
				if (session.isOpen()) {
					session.close();
				}
			}
		}
		
	}

}
